home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 28
/
Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso
/
Aminet
/
dev
/
c
/
dice-3.16.lha
/
doc
/
rexx.doc
< prev
next >
Wrap
Text File
|
1994-02-13
|
26KB
|
780 lines
DICE AREXX SUPPORT
XXX handle sending a command w/ multiple arguments
XXX handle custom returns of messages
DICE maintains several routines to automatically handle most of the
grunt work involved in writing a program with AREXX support, you as
a programmer need only setup part of the event loop and the command
dispatch. By calling DICE's ARexx support routines you automatically
cause DICE to bring in startup and exit code to maintain it.
The first thing you need to do is declare char *RexxHostName; You have
two choices (example).
char *RexxHostName = "DME";
char *RexxHostName = NULL;
The first case is the most common -- by declaring RexxHostName with a
string DICE will automatically setup its ARexx subsystem and
automatically create an application ARexx port, finding an appropriate
slot number 01 through 99 (the actual port will be named DME.nn where nn
is 01 through 99). Note that DICE sets up its ARexx subsystem BEFORE
YOUR MAIN() IS CALLED, so the assignment to RexxHostName must be part
of the declaration.
The second case, declaring RexxHostName to be NULL, causes DICE to
setup it's ARexx subsystem but *NOT* create any ARexx ports. Your
main() must then create a Global ARexx port using:
r = CreateGlobalDiceRexxPort(NULL, char *globalName);
Passing NULL as the message port causes DICE to initialize it's
internal RexxPort structure as a global ARexx message port.
If you do not do either of the above two steps beware that DICE's
internal RexxPort will be invalid and unusable.
Regardless of how you initialize RexxHostName, DICE will automatically
open rexxsyslib.library for you. DICE can handle an arbitrary number
of nesting levels and multiple ARexx ports simultaniously. Finally,
DICE fully resource tracks all ARexx operations done through this
interface, including messages in progress, allowing ^C BREAK to be
operational at all times! That is, DICE WILL AUTOMATICALLY CLEANUP
THE MESS THAT IS LEFT IF SOMEONE BREAK's THE PROGRAM 5 NESTING LEVELS
DEEP.
DICE's automatic AREXX support is brought in if you reference any DICE
ARexx command such as ProcessRexxCommands() (which you need to have
for your part of the interface anyway).
You can, at any time, create and destroy DICE supported ARexx ports.
This is done via the CreateDiceRexxPort(), CreateGlobalDiceRexxPort()
calls, and DeleteDiceRexxPort) calls. CreateDiceRexxPort() will modify
your supplied port name with a slot number, finding a free slot number
and returning it (-1 on failure). CreateGlobalDiceRexxPort() will
not modify your supplied port name. If you pass NULL as the port name
for either routine DICE will create a private ARexx port instead of a
public one.
------------------------------ EXAMPLE 1 -----------------------------
This example shows how to setup a global port to redirect commands to
the proper instance of the application.
1> dcc gtest.c -o gtest
1> run gtest
1> run gtest a
1> run gtest b
1> rx gtest.rexx
The first instance of the program, gtest without arguments, sets up a
global port called "GTEST". Each of the other instances of the program
setup application ports "GTEST.xx". The rexx script sends a command
to the global port and the first gtest process then scans through all
possible application ports sending the command to them until one
returns success.
If you run the above you will note that the 'a' and 'b' commands in
the rexx script succeeded but the 'c' command failed. If you now run
a gtest to handle c:
1> run gtest c
And run the rexx script again, all will succeed.
#include <lib/rexx.h>
#include <clib/exec_protos.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <dos/dos.h>
char Buf[256];
/*
* This program shows off using a global port for the program verses
* an application port. You run the program as follows:
*
*/
char *RexxHostName = NULL; /* no automatic start */
char *MyCommand; /* left NULL for global port */
main(ac, av)
char *av[];
{
/*
* DICE automatically opens rexxsyslib.library for us as long
* as we reference the base variable (via extern) and not
* declare it. lib/rexx.h does this for us.
*
* However, unlike other autoinits, if DICE is unable to open
* the library it does not abort the program, hence the following.
*/
if (RexxSysBase == NULL) {
puts("Unable to open rexxsyslib.library !");
exit(20);
}
/*
* We left RexxHostName = NULL because our program will create
* either a global port or an application port and we don't know
* which one yet.
*
* Our call to Create[Global]DiceRexxPort(NULL, ...) will cause
* DICE to initialize our RexxHostName properly.
*/
if (ac == 1) { /* no arguments, create global port */
short r = CreateGlobalDiceRexxPort(NULL, "GTEST");
if (r < 0) {
puts("Unable to create global port GTEST, already exists?");
exit(20);
}
printf("Created global port for redirect to proper app\n");
} else { /* arguments, create local app port */
short r = CreateDiceRexxPort(NULL, "GTEST");
if (r < 0) {
puts("Unable to create application port GTEST!");
exit(20);
}
printf("Created application port GTEST.%02d for '%s'\n", r, av[1]);
MyCommand = av[1];
}
{
char *ptr;
int slotNo;
slotNo = GetDiceRexxPortSlot(NULL, &ptr);
printf("slot: %d '%s'\n", slotNo, ptr);
}
/*
* Our main loop executes received commands
*/
for (;;) {
long mask = Wait(SIGBREAKF_CTRL_C | (1 << RexxSigBit));
if (mask & SIGBREAKF_CTRL_C) {
printf("Terminating %s\n", (ac == 1) ? "global" : av[1]);
exit(1);
}
if (mask & (1 << RexxSigBit))
ProcessRexxCommands(NULL);
}
}
/*
* Our command handler depends on MyCommand... do we attempt to
* execute the command or do we attempt to pass it on to application
* ports ?
*/
long
DoRexxCommand(msg, port, arg0, pres)
void *msg; /* RexxMsg structure if we need it */
struct MsgPort *port; /* MsgPort structure if we need it */
char *arg0; /* arg0 */
char **pres; /* where to put our result if rc==0 */
{
int rc;
if (MyCommand == NULL) {
short i;
char buf[32];
printf("Global Redirect command: %s\n", arg0);
for (i = 1; i < 100; ++i) {
sprintf(buf, "%s.%02d", RexxHostName, i);
if ((rc = PlaceRexxCommandDirect(NULL, buf, arg0, pres, NULL)) == 0)
break;
}
if (i == 100) {
printf("Global: Command failed\n");
rc = 5;
}
} else {
printf("MatchCheck %s vs %s\n", arg0, MyCommand);
if (stricmp(arg0, MyCommand) == 0) {
*pres = "success!";
rc = 0;
} else {
*pres = "failure";
rc = 5;
}
}
return(rc);
}
--------- gtest.rexx --------
/* gtest */
OPTIONS RESULTS
address GTEST
RESULT = 'no result'
a
say RC ',' RESULT
RESULT = 'no result'
b
say RC ',' RESULT
RESULT = 'no result'
c
say RC ',' RESULT
------------------------------ EXAMPLE 2 -----------------------------
This example shows off DICE's capability to arbitrarily nest ARexx
commands.
To test, run the program in one CLI and the rexx script in another.
Try running the rexx script without typing ^E from the test program,
then try running the rexx script after typing ^E from the test program
(to enable the second ARexx port).
Finally, just for fun, try ^C (BREAKing) your test program while it's
in the middle of processing ARexx commands.
1> dcc test.c -o test
1> test
...
2> rx xx.rexx
etc...
#include <lib/rexx.h>
#include <clib/exec_protos.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <dos/dos.h>
char Buf[256];
/*
* This program shows off using two ports. The first is created
* automatical